Forbid usage of Build.Version.SDK_INT in favor of sdkVersion#6874
Forbid usage of Build.Version.SDK_INT in favor of sdkVersion#6874TimoPtr wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a test-friendly sdkVersion provider (with isAtLeast(api) gates recognized by Android Lint) and adds a custom lint rule to forbid direct reads of Build.VERSION.SDK_INT, then migrates the codebase to use the new provider for SDK version checks.
Changes:
- Added
SdkVersionProvider+ globalsdkVersionoverride point for tests, and replaced mostBuild.VERSION.SDK_INTchecks withsdkVersion.isAtLeast(...) - Added a lint check (
SdkVersionAccess) (with unit tests) to prevent new directSDK_INTusage - Updated permission/version-dependent code paths across app/common/wear (and adjusted affected tests)
Reviewed changes
Copilot reviewed 96 out of 96 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt | Switch haptic gating from SDK_INT to sdkVersion |
| wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt | Use sdkVersion for permission gating |
| wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt | Use sdkVersion for API-availability flag |
| wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt | Use sdkVersion for sensor availability |
| wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt | Replace SDK checks and log SDK via sdkVersion |
| wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt | Use sdkVersion for permission UI logic |
| wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt | Use sdkVersion for notification permission gating |
| lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt | Add tests for new lint detector and suppression behavior |
| lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt | New lint detector forbidding Build.VERSION.SDK_INT reads |
| lint/src/main/kotlin/io/homeassistant/lint/LintRegistry.kt | Register SdkVersionAccess issue |
| common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt | Provide OS version string via sdkVersion.toString() |
| common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt | Use sdkVersion for notification channel creation gating |
| common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt | New provider + global sdkVersion with test-only setter |
| common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt | Use sdkVersion for N+ active-notification APIs |
| common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt | Gate HttpEngine usage via sdkVersion |
| common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt | Replace SDK checks with sdkVersion |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt | Use sdkVersion for permission requirements |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt | Use sdkVersion for foreground service type + channel gating |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt | Use sdkVersion for notification channel gating |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt | Use sdkVersion for PackageManager/AppOps API branching |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt | Use sdkVersion for feature branching |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt | Replace multiple SDK gates with sdkVersion |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt | Use sdkVersion for permission + telephony API branching |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt | Use sdkVersion for Bluetooth permission branching |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt | Replace SDK gates with sdkVersion |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt | Use sdkVersion for update type + sensor availability |
| common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt | Use sdkVersion for API-dependent sensors |
| common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt | Use sdkVersion for notification channel and settings gating |
| common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt | Use sdkVersion for getSerializableExtra overload branching |
| common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt | Use sdkVersion for UNKNOWN_SSID behavior branching |
| common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt | Use sdkVersion for time parsing capability gating |
| common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt | Use sdkVersion for adaptive icon support gating |
| common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt | Use sdkVersion for channel creation gating |
| app/src/test/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManagerTest.kt | Switch tests to override global sdkVersion instead of ctor param |
| app/src/minimal/kotlin/io/homeassistant/companion/android/location/LocationProvider.kt | Use sdkVersion for provider selection |
| app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetState.kt | Use sdkVersion for dynamic color background gating |
| app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt | Use sdkVersion for pin-widget gating |
| app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt | Use sdkVersion for pin-widget gating |
| app/src/main/kotlin/io/homeassistant/companion/android/widgets/mediaplayer/MediaPlayerControlsWidgetConfigureActivity.kt | Use sdkVersion for pin-widget gating |
| app/src/main/kotlin/io/homeassistant/companion/android/widgets/entity/EntityWidgetConfigureActivity.kt | Use sdkVersion for pin-widget gating |
| app/src/main/kotlin/io/homeassistant/companion/android/widgets/camera/CameraWidgetConfigureActivity.kt | Use sdkVersion for pin-widget gating |
| app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt | Use sdkVersion for pin-widget gating |
| app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt | Default notification-permission support via sdkVersion |
| app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt | Replace SDK gates (lockscreen, download, WebView pkg, LAN perm, PiP) |
| app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt | Use sdkVersion for channels/foreground service type gating |
| app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt | Use sdkVersion for Android 14 display security workaround |
| app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt | Use sdkVersion for Android 14 display security workaround |
| app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt | Use sdkVersion for scoped storage + channel creation gating |
| app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt | Use sdkVersion for connectivity API branching |
| app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt | Use sdkVersion for night mode implementation branching |
| app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt | Use sdkVersion for permission set composition |
| app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt | Use sdkVersion to choose default theme behavior |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt | Use sdkVersion for pin-widget support detection |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt | Use sdkVersion for notification settings visibility gating |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt | Use sdkVersion for UNKNOWN_SSID behavior branching |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt | Use sdkVersion for location permission branching |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt | Use sdkVersion for shortcut pinning gates |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt | Use sdkVersion for notification suggestion gating |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt | Replace many preference visibility SDK gates with sdkVersion |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt | Use sdkVersion for notification-channel info visibility |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt | Use sdkVersion for PackageManager overload branching and permission flow |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt | Use sdkVersion for background-location request branching |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt | Use sdkVersion for subtitle support gating |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt | Use sdkVersion for add-vs-save behavior and tile add flow |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt | Use sdkVersion for intent query overload branching |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt | Use sdkVersion for locale migration/application branching |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt | Use sdkVersion for Controls Panel availability branching |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt | Use sdkVersion for Controls Panel enable/disable gating |
| app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt | Use sdkVersion for RoleManager gate |
| app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt | Use sdkVersion for channelId exposure gating |
| app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt | Use sdkVersion for PackageManager overload branching |
| app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt | Use sdkVersion for permission set + Geocoder overload branching |
| app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt | Use sdkVersion for API availability gating |
| app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt | Use sdkVersion for BundleCompat parcelable branching |
| app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt | Use sdkVersion for subtitle and vibration API branching |
| app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt | Use sdkVersion for local network permission requirement gating |
| app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt | Use sdkVersion for NSD stopServiceResolution API gate |
| app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt | Replace multiple SDK gates with sdkVersion (channels, groups, Bluetooth, live, etc.) |
| app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt | Use sdkVersion for PiP gating |
| app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt | Use sdkVersion for UNKNOWN_SSID behavior branching |
| app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt | Use sdkVersion for Bluetooth permission requirements |
| app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt | Replace SDK checks and log SDK via sdkVersion |
| app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt | Remove test-only sdkInt ctor param; gate with sdkVersion |
| app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt | Use sdkVersion for haptic API branching |
| app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt | Use sdkVersion for domain minimum API filtering and auth-required gate |
| app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt | Use sdkVersion for Control#setAuthRequired gate |
| app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt | Use sdkVersion for foreground-service and channel API gates |
| app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt | Use sdkVersion for T+ behavior gating |
| app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt | Use sdkVersion for lockscreen behavior branching |
| app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt | Use sdkVersion for Thread support gating |
| app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt | Use sdkVersion for accuracy fields + permission branching |
| app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt | Use sdkVersion for availability gating |
| app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt | Use sdkVersion for ACTIVITY_RECOGNITION permission gating |
| app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt | Use sdkVersion for commissioning support gating |
| app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt | Use sdkVersion for channel creation and service type gating |
| app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt | Use sdkVersion for lifecycle behavior gating |
| @AfterEach | ||
| fun tearDown() { | ||
| sdkVersion = SdkVersionProvider { false } | ||
| } |
There was a problem hiding this comment.
See my description, I don't know yet what to do there.
There was a problem hiding this comment.
@jpelgrom I could actually make it fail if the test code is reaching the Provider so it force us to handle the case wdyt?
| /** | ||
| * Reports whether the current Android SDK level is at least [api]. Tests can substitute a fake | ||
| * provider to simulate a SDK version. | ||
| * |
| @SuppressLint("ObsoleteSdkInt") // Needed for app module (minSdk 21) but obsolete for automotive (minSdk 29) | ||
| private val areCarSensorApisAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O | ||
| private val areCarSensorApisAvailable = sdkVersion.isAtLeast(Build.VERSION_CODES.O) |
There was a problem hiding this comment.
Oh nice it means we won't have the issue anymore with the Automotive. In any case I was even wondering about dropping this lint check because it was more annoying than useful, last time I dropped a first I went over all the Build.VERSION_CODES bellow the one set as minimal.
Summary
Using
Build.Version.SDK_INTmakes testing some branches impossible because of that we used to do some ugly constructor that has thesdkInthas parameter. I found out the existence of https://developer.android.com/reference/androidx/annotation/ChecksSdkIntAtLeast that allow a method to tell the linter that it properly test this specific version. I've created a static field namedsdkVersionthat helps replace all the usage of theSDK_INTand a lint rule to forbid the usage ofSDK_INTdirectly.I used the same pattern as the one we have in
HomeAssistantVersionwithatLeast. We cannot override thecompareTooperator but I think it is more explicit in the end to useatLeast. We also connot make itinfixthe annotation doesn't support it.This PR is split in multiple commits to ease the review, the first commit is the actual logic, the second is the replace of all the usage.
Checklist
Any other notes
I did not create a rule for test to reset the version since it was already something we had to handle manually but we might reconsider later.